<template>
  <el-select class="select-cascader" popper-class="select-cascader-panel" :value="optionValue" @clear="handleClear" filterable :clearable="$attrs.clearable" :disabled="$attrs.disabled || $attrs.readonly" :filter-method="handleInput" @visible-change="(params) => $emit('visible-change', params)">
    <slot />
    <el-option ref="el-option" v-show="false" :label="optionLabel" :value="optionValue">
      <span class="span-ellipsis">
        <span :title="optionLabel">{{optionLabel}}</span>
      </span>
    </el-option>
    <el-cascader-panel v-show="!filtering" ref="cascader" style="width: 100%" v-model="model" :border="false" v-bind='{
        props:config,
        ...$attrs
      }' @change="change">

    </el-cascader-panel>
    <el-scrollbar @keydown.native="handleSuggestionKeyDown" ref="suggestionPanel" v-if="$attrs.filterable" v-show="filtering" tag="ul" class="el-cascader__suggestion-panel" view-class="el-cascader__suggestion-list">
      <template v-if="suggestions.length">
        <li v-for="(item) in suggestions" :key="item.uid" :class="[
              'el-cascader__suggestion-item',
              item.checked && 'is-checked'
            ]" :tabindex="-1"
            @click="handleSuggestionClick(index)">
          <span>{{ item.text }}</span>
          <i v-if="item.checked" class="el-icon-check"></i>
        </li>
      </template>
      <slot v-else name="empty">
        <li class="el-cascader__empty-text">没有数据</li>
      </slot>
    </el-scrollbar>
    <!-- <el-tree
      :style="{'width': width + 'px'}"
      ref="el-tree"
      class="select-tree"
      :data="treeData"
      :props="defaultPropsName"
      :node-key="defaultPropsName.value"
      :show-checkbox="showCheckbox"
      highlight-current
      check-on-click-node
      :expand-on-click-node="false"
      default-expand-all
      :filter-node-method="filterNode"
      @node-click="handleNodeClick"
      @current-change="handleCurrentChange"
    >
      <span class="span-ellipsis" slot-scope="{ node }">
        <span :title="node.label">{{node.label}}</span>
      </span>
    </el-tree> -->
  </el-select>
</template>

<script>

import { isUndefined, isFunction } from 'element-ui/src/utils/types';
import { isEqual, isEmpty, kebabCase } from 'element-ui/src/utils/util';
import { isDef } from 'element-ui/src/utils/shared';
import debounce from 'throttle-debounce/debounce';

import AriaUtils from 'element-ui/src/utils/aria-utils';
const { keys: KeyCode } = AriaUtils;

const MigratingProps = {
  expandTrigger: {
    newProp: 'expandTrigger',
    type: String
  },
  changeOnSelect: {
    newProp: 'checkStrictly',
    type: Boolean
  },
  hoverThreshold: {
    newProp: 'hoverThreshold',
    type: Number
  }
};

export default {
  name: 'BaseCascader',
  props: {
    value: {
      type: Array,
      default: () => ([])
    },
    beforeFilter: {
      type: Function,
      default: () => () => { }
    },
    showAllLevels: {
      type: Boolean,
      default: true
    },
    separator: {
      type: String,
      default: ' / '
    },
    disabled: Boolean,
    clearable: Boolean,
    filterable: Boolean,
    popperClass: String,
    props: Object,
    filterMethod: Function,
    placeholder: {
      type: String,
      default: () => '请选择'
    },
    debounce: {
      type: Number,
      default: 300
    }
  },
  data () {
    return {
      filtering: false,
      suggestions: [],
      selectValue: undefined,
      model: undefined,
      optionLabel: '',
      optionValue: '',
      defaultProps: {
        children: 'children',
        label: 'label',
        value: 'value'
      }
    }
  },
  computed: {
    defaultPropsName () {
      return this.$attrs.defaultProps || this.defaultProps
    },
    config () {
      const config = this.props || {};
      const { $attrs } = this;

      Object
        .keys(MigratingProps)
        .forEach(oldProp => {
          const { newProp, type } = MigratingProps[oldProp];
          let oldValue = $attrs[oldProp] || $attrs[kebabCase(oldProp)];
          if (isDef(oldProp) && !isDef(config[newProp])) {
            if (type === Boolean && oldValue === '') {
              oldValue = true;
            }
            config[newProp] = oldValue;
          }
        });

      return config;
    },
    leafOnly () {
      return !this.config.checkStrictly;
    },
    multiple () {
      return this.config.multiple;
    }
  },
  watch: {
    value (val) {
      this.setOption(val);
    }
  },
  created () {
    this.filterHandler = debounce(this.debounce, (val) => {
      // const { optionValue } = this;

      if (!val) {
        this.filtering = false;
        return;
      }

      const before = this.beforeFilter(val);
      if (before && before.then) {
        before.then(() => this.getSuggestions(val));
      } else if (before !== false) {
        this.getSuggestions(val);
      } else {
        this.filtering = false;
      }
    });
  },
  methods: {
    handleClear () {
      this.change();
      this.$refs['cascader'].clearCheckedNodes();
    },
    handleSuggestionClick (index) {
      const targetNode = this.suggestions[index];

      const data = targetNode.getValueByOption();
      this.change(data);
    },
    handleSuggestionKeyDown (event) {
      const { keyCode, target } = event;
      switch (keyCode) {
        case KeyCode.enter:
          target.click();
          break;
        case KeyCode.up:
          // eslint-disable-next-line
          const prev = target.previousElementSibling;
          prev && prev.focus();
          break;
        case KeyCode.down:
          // eslint-disable-next-line
          const next = target.nextElementSibling;
          next && next.focus();
          break;
        case KeyCode.esc:
        case KeyCode.tab:
          this.toggleDropDownVisible(false);
          break;
      }
    },
    handleInput (val, event) {
      if (event && event.isComposing) return;
      if (val) {
        this.filterHandler(val);
      } else {
        this.filtering = false;
      }
    },
    getSuggestions (val) {
      let { filterMethod } = this;

      if (!isFunction(filterMethod)) {
        filterMethod = (node, keyword) => node.text.includes(keyword);
      }

      const suggestions = this.$refs['cascader'].getFlattedNodes(this.leafOnly)
        .filter(node => {
          if (node.isDisabled) return false;
          debugger
          node.text = node.getText(this.showAllLevels, this.separator) || '';
          return filterMethod(node, val);
        });

      this.filtering = true;
      this.suggestions = suggestions;
      // this.$nextTick(this.updatePopper);
    },
    // 节点选中时的回调
    change (data) {
      this.$emit('input', data)
    },
    setOption (val) {
      this.model = val;
      this.$nextTick(() => {
        const checkedNodes = this.$refs['cascader'].getCheckedNodes();
        if (checkedNodes && checkedNodes.length > 0) {
          this.optionLabel = checkedNodes.map(node => node.label).join(' / ');
          this.optionValue = val;
        }
      })
    }

    // // 树节点过滤方法
    // filterNode (value, data) {
    //   if (!value) return true;
    //   return data.title.indexOf(value) !== -1;
    // }
  },
  mounted () {
  }
};
</script>

<style lang="scss" scoped>
  .select-cascader{
    width: 100%;
  }
</style>

<style lang="scss">
.select-cascader-panel {
  .el-select-dropdown__empty {
    display: none;
  }
  .el-cascader-panel {
    width: 100%;
    border: 0;
    .el-cascader-menu {
      width: 100%;
    }
  }
}

.span-ellipsis {
  display: inline-block;
  // max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 14px;
}
</style>
